//=============================================================================

#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include "../../../../inc/aString.h"

//=============================================================================

aString::aString() : charSize(sizeof(wchar_t))
{
  m_Length = 0;
  m_pData = 0;
  m_pCharData = 0;
  codePage = CP_UTF8;
  codePageW = CP_UTF8;
}

//=============================================================================

aString::aString(const wchar_t* str) : charSize(sizeof(wchar_t))
{
  m_Length = 0;
  m_pData = 0;
  m_pCharData = 0;
  codePage = CP_UTF8;
  codePageW = CP_UTF8;

  if (!str)
    return;

  size_t strLen = wcslen(str);
  
  m_pData = new wchar_t[strLen + 1];
  m_pCharData = new char[strLen + 1];
  memcpy(m_pData, str, strLen*charSize);
  m_pData[strLen] = 0;

  WideCharToMultiByte(codePage, 0, m_pData, strLen, m_pCharData, strLen, 0, 0);
  m_pCharData[strLen] = 0;

  m_Length = strLen;
}

//=============================================================================

aString::aString(const char* str) : charSize(sizeof(wchar_t))
{
  m_Length = 0;
  m_pData = 0;
  m_pCharData = 0;
  codePage = CP_UTF8;
  codePageW = CP_UTF8;

  if (!str)
    return;

  size_t strLen = strlen(str);
  
  m_pData = new wchar_t[strLen + 1];
  m_pCharData = new char[strLen + 1];
  memcpy(m_pCharData, str, strLen);
  m_pCharData[strLen] = 0;

	MultiByteToWideChar(0, 0, m_pCharData, strLen, m_pData, strLen);
  m_pData[strLen] = 0;

  m_Length = strLen;
}

//=============================================================================

aString::aString(const aString& str) : charSize(sizeof(wchar_t))
{
  m_Length = 0;
  m_pData = 0;
  m_pCharData = 0;
  codePage = CP_UTF8;
  codePageW = CP_UTF8;

  if (str.asGetLength() <= 0)
    return;

  const wchar_t* tmpPointer = str.asGetString();
  size_t strLen = wcslen(tmpPointer);
  
  m_pData = new wchar_t[strLen + 1];
  m_pCharData = new char[strLen + 1];
  memcpy(m_pData, tmpPointer, strLen*charSize);
  m_pData[strLen] = 0;

  WideCharToMultiByte(codePage, 0, m_pData, strLen, m_pCharData, strLen, 0, 0);
  m_pCharData[strLen] = 0;

  m_Length = strLen;
}

//=============================================================================

bool aString::operator==(const aString& str)
{
  if (str.asGetLength() != m_Length)
    return 0;

  wchar_t* tmpPointer = m_pData;
  const wchar_t* tmpPointer2 = str.asGetString();
  
  while(*tmpPointer != L'\0')
  {
    if (*tmpPointer++ != *tmpPointer2++)
      return 0;
  }

  return 1;
}

//=============================================================================

bool aString::operator==(const wchar_t* str)
{
  if (!str)
    return 0;

  if (wcslen(str) != m_Length)
    return 0;

  wchar_t* tmpPointer = m_pData;
  
  while(*tmpPointer != L'\0')
  {
    if (*tmpPointer++ != *str++)
      return 0;
  }

  return 1;
}


//=============================================================================

bool aString::operator==(const char* str)
{
  if (!str || !m_pCharData)
    return 0;

  if (strlen(str) != m_Length)
    return 0;

  char* tmpPointer = m_pCharData;
  
  while(*tmpPointer != L'\0')
  {
    if (*tmpPointer++ != *str++)
      return 0;
  }

  return 1;
}

//=============================================================================

bool aString::operator!=(const aString& str)
{
  if (str.asGetLength() != m_Length)
    return 1;

  wchar_t* tmpPointer = m_pData;
  const wchar_t* tmpPointer2 = str.asGetString();
  
  while(*tmpPointer != L'\0')
  {
    if (*tmpPointer++ != *tmpPointer2++)
      return 1;
  }

  return 0;
}

//=============================================================================

bool aString::operator!=(const wchar_t* str)
{
  if (!str)
    return 1;

  if (wcslen(str) != m_Length)
    return 1;

  wchar_t* tmpPointer = m_pData;
  const wchar_t* tmpPointer2 = str;
  
  while(*tmpPointer != L'\0')
  {
    if (*tmpPointer++ != *tmpPointer2++)
      return 1;
  }

  return 0;
}

//=============================================================================

bool aString::operator!=(const char* str)
{
  if (!str)
    return 1;

  if (strlen(str) != m_Length)
    return 1;

  wchar_t* tmpPointer = m_pData;
  
  while(*tmpPointer != L'\0')
  {
    if (*tmpPointer++ != *str++)
      return 1;
  }

  return 0;
}

//=============================================================================

const aString& aString::operator=(const aString& str)
{
  if (str.asGetLength() <= 0)
    return (*this);

  asClear();

  const wchar_t* tmpPointer = str.asGetString();
  size_t strLen = wcslen(tmpPointer);
  
  m_pData = new wchar_t[strLen + 1];
  m_pCharData = new char[strLen + 1];
  memcpy(m_pData, tmpPointer, strLen*charSize);
  m_pData[strLen] = 0;

  WideCharToMultiByte(codePage, 0, m_pData, strLen, m_pCharData, strLen, 0, 0);
  m_pCharData[strLen] = 0;

  m_Length = strLen;

  return (*this);
}

//=============================================================================

const aString& aString::operator=(const wchar_t* str)
{
  if (!str)
    return (*this);

  asClear();

  size_t strLen = wcslen(str);
  
  m_pData = new wchar_t[strLen + 1];
  m_pCharData = new char[strLen + 1];
  memcpy(m_pData, str, strLen*charSize);
  m_pData[strLen] = 0;

  WideCharToMultiByte(codePage, 0, m_pData, strLen, m_pCharData, strLen, 0, 0);
  m_pCharData[strLen] = 0;

  m_Length = strLen;

  return (*this);
}

//=============================================================================

const aString& aString::operator=(const char* str)
{
  if (!str)
    return (*this);

  asClear();

  size_t strLen = strlen(str);
  
  m_pData = new wchar_t[strLen + 1];
  m_pCharData = new char[strLen + 1];
  memcpy(m_pCharData, str, strLen);
  m_pData[strLen] = 0;

	MultiByteToWideChar(codePageW, 0, m_pCharData, strLen, m_pData, strLen);
  m_pCharData[strLen] = 0;

  m_Length = strLen;

  return (*this);
}

//=============================================================================

const aString aString::operator+=(const aString& str)
{
  if (str.asGetLength() <= 0)
    return (*this);

  size_t newLength = str.asGetLength() + m_Length;
  wchar_t* newData = new wchar_t[newLength + 1];
  char* newData2 = new char[newLength + 1];

  memcpy(newData, m_pData, m_Length*charSize);
  memcpy(&newData[m_Length], str.asGetString(), str.asGetLength()*charSize);
  newData[newLength] = 0;
  
  delete [] m_pData;
  delete [] m_pCharData;

  WideCharToMultiByte(codePage, 0, newData, newLength, newData2, newLength, 0, 0);
  newData2[newLength] = 0;

  m_pData = newData;
  m_pCharData = newData2;
  m_Length = newLength;

  return (*this);
}

//=============================================================================

const aString aString::operator+=(const wchar_t* str)
{
  if (!str)
    return (*this);

  size_t tmpLength = wcslen(str);

  if (tmpLength <= 0)
    return (*this);

  size_t newLength = tmpLength + m_Length;
  wchar_t* newData = new wchar_t[newLength + 1];
  char* newData2 = new char[newLength + 1];

  memcpy(newData, m_pData, m_Length*charSize);
  memcpy(&newData[m_Length], str, tmpLength*charSize);
  newData[newLength] = 0;
  
  delete [] m_pData;
  delete [] m_pCharData;

  WideCharToMultiByte(codePage, 0, newData, newLength, newData2, newLength, 0, 0);
  newData2[newLength] = 0;

  m_pData = newData;
  m_pCharData = newData2;
  m_Length = newLength;

  return (*this);
}

//=============================================================================

const aString aString::operator+=(wchar_t str)
{
  size_t newLength = m_Length + 1;
  wchar_t* newData = new wchar_t[newLength + 1];

  memcpy(newData, m_pData, m_Length*charSize);
  memcpy(&newData[m_Length], &str, charSize);
  newData[newLength] = 0;
  
  if (m_Length > 0)
    delete [] m_pData;

  m_pData = newData;
  m_Length = newLength;

  return (*this);
}

//=============================================================================

const aString aString::operator+(const aString& str)
{
  size_t tmpLength = str.asGetLength();

  if (tmpLength <= 0)
    return (*this);

  size_t newLength = tmpLength + m_Length;
  wchar_t* newData = new wchar_t[newLength + 1];
  aString tmp;

  memcpy(newData, m_pData, m_Length*charSize);
  memcpy(&newData[m_Length], str.asGetString(), tmpLength*charSize);
  newData[newLength] = 0;

  tmp = newData;

  delete [] newData;
  
  return tmp;
}

//=============================================================================

const aString aString::operator+(const wchar_t* str)
{
  if (!str)
    return (*this);

  size_t tmpLength = wcslen(str);

  if (tmpLength <= 0)
    return (*this);

  size_t newLength = tmpLength + m_Length;
  wchar_t* newData = new wchar_t[newLength + 1];
  aString tmp;

  memcpy(newData, m_pData, m_Length*charSize);
  memcpy(&newData[m_Length], str, tmpLength*charSize);
  newData[newLength] = 0;

  tmp = newData;
  
  delete [] newData;

  return tmp;
}

//=============================================================================

aString aString::asFindBefore(wchar_t chr, bool include) const
{
  wchar_t* tmpPointer = m_pData;
  aString res;

  while(*tmpPointer != L'\0')
  {
    if (*tmpPointer != chr)
      res += *tmpPointer++;
    else
    {
      if (include)
        res += *tmpPointer;

      break;
    }
  }

  return res;
}

//=============================================================================

aString aString::asFindAfter(wchar_t chr, bool include) const
{
  wchar_t* tmpPointer = m_pData;
  aString res;
  bool find = 0;

  while(*tmpPointer != L'\0')
  {
    if ((*tmpPointer == chr) && (!find))
    {
      find = 1;
      if (!include)
      {
        ++tmpPointer;

        continue;
      }
    }

    if (find)
      res += *tmpPointer;

    ++tmpPointer;
  }

  return res;
}

//=============================================================================

void aString::asClear()
{
  if (m_pData)
  {
    delete [] m_pData;

    m_pData = 0;
  }
  if (m_pCharData)
  {
    delete [] m_pCharData;

    m_pCharData = 0;
  }
  m_Length = 0;
}

//=============================================================================

void aString::asGetWords(aList<aString>& list) const
{
  list.alRemoveItems();

  wchar_t* tmpPointer = m_pData;
  aString tmpString;

  while(*tmpPointer != '\0')
  {
    if (int(*tmpPointer) == 32)
    {
      list.alAddItem()->data = tmpString;
      tmpString.asClear();
    }
    else
      tmpString += *tmpPointer;
    ++tmpPointer;
  }
  list.alAddItem()->data = tmpString;
}

//=============================================================================

const aString aString::asAcceptWithParams(const char* str, ...)
{
  if (!str)
    return "";

  char buff[DEFAULT_BUFFSIZE] = {0};
  va_list ap;

  va_start(ap, str);
  vsprintf(buff, str, ap);
  va_end(ap);

  size_t strLen = strlen(buff);
  
  m_pData = new wchar_t[strLen + 1];
  m_pCharData = new char[strLen + 1];
  memcpy(m_pCharData, buff, strLen);
  m_pCharData[strLen] = 0;

	MultiByteToWideChar(0, 0, m_pCharData, strLen, m_pData, strLen);
  m_pData[strLen] = 0;

  m_Length = strLen;

  return (*this);
}

//=============================================================================

aString::~aString()
{
  asClear();
}

//=============================================================================
